﻿using System;
using RayDen.Library.Components;
using RayDen.Library.Components.Color;
using RayDen.Library.Core.Components;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Imaging;
using RayDen.RayEngine;

namespace Lt.Managers
{
    public class ColorManager : Singleton<ColorManager>
    {
        private readonly IRadianceEvaluation unit;
        private readonly IRadianceEvaluation zero;
        private bool sampledSpectrum;

        public ColorManager()
            : this(GlobalConfiguration.Instance.SpectralRendering)
        {
        }

        public ColorManager(bool spectral = false)
        {
            sampledSpectrum = spectral;
            if (spectral)
            {
                unit = new SpectralRadiance(SampledSpectrum.UnitSpectrum());
                zero = new SpectralRadiance(SampledSpectrum.ZeroSpectrum());
            }
            else
            {
                unit = new RgbRadiance(RgbSpectrum.UnitSpectrum());
                zero = new RgbRadiance(RgbSpectrum.ZeroSpectrum());
            }
        }
        public IRadianceEvaluation UnitRadiance()
        {
            return unit.Clone();
        }

        public IRadianceEvaluation ZeroRadiance()
        {
            return zero.Clone();
        }

        public RgbSpectrum Convert(IRadianceEvaluation radiance)
        {
            RgbSpectrum result;
            radiance.ToRgbSpectrum(out result);
            return result;
        }

        public IRadianceEvaluation Convert(ref RgbSpectrum rgb, bool emission = false)
        {
            if (sampledSpectrum)
            {
                return new SpectralRadiance(ColorFactory.SSEFromRgb(ref rgb, emission ? SpectrumType.Illuminant : SpectrumType.Reflectance));
            }

            return new RgbRadiance(ref rgb);
        }

        public IRadianceEvaluation Convert(ref SampledSpectrum spc, bool emission = false)
        {
            if (sampledSpectrum)
            {
                return new SpectralRadiance(ref spc);
            }

            return new RgbRadiance(spc.ToRgb());
        }


        public IRadianceEvaluation Create(float[] emissionSpectra, bool emission)
        {
            if (emissionSpectra.Length == 3)
            {
                if (sampledSpectrum)
                {
                    return new SpectralRadiance(new SampledSpectrum(ColorFactory.SSEFromRgb(emissionSpectra, SpectrumType.Illuminant)));
                }

                return new RgbRadiance(new RgbSpectrum(emissionSpectra));

                //return new RgbRadiance(new SampledSpectrum(ColorFactory.SSEFromRgb(emissionSpectra, SpectrumType.Illuminant)).ToRgb());
            }

            if (sampledSpectrum)
            {
                return new SpectralRadiance(new SampledSpectrum(emissionSpectra));
            }

            return new RgbRadiance(new SampledSpectrum(emissionSpectra).ToRgb());
        }
    }
}
